﻿using Acl.Log;

using Microsoft.Extensions.Logging;

namespace Acl.WinFormHosting.Services;

class AclLogProvider : ILoggerProvider
{
    public static readonly ILoggerProvider Instance = new AclLogProvider();
    public ILogger CreateLogger(String categoryName) => new AclLogger(Acl.Log.LogManager.GetLogger(categoryName));

    public void Dispose() { }
}

class AclLogger : ILogger
{
    internal Acl.Log.ILog _innerLogger;
    public AclLogger(Acl.Log.ILog innerLogger) => _innerLogger = innerLogger;

    public IDisposable? BeginScope<TState>(TState state) where TState : notnull => NullDisposable.Instance;

    private static AsyncLocal<bool> _enabled = new();
    internal void MarkDisable() => _enabled.Value = false;
    internal void MarkEnabled() => _enabled.Value = true;



    public Boolean IsEnabled(Microsoft.Extensions.Logging.LogLevel logLevel)
    {
        var currentLevel = (Microsoft.Extensions.Logging.LogLevel)Acl.Log.LogManager.Current.Settings.Root.Level;
        if (currentLevel <= logLevel)
        {
            return _enabled.Value;
        }
        return false;
    }

    public void Log<TState>(Microsoft.Extensions.Logging.LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, String> formatter)
    {
        if (_innerLogger.Enabled == false) return;

        var currentLevel = (Microsoft.Extensions.Logging.LogLevel)Acl.Log.LogManager.Current.Settings.Root.Level;
        if (currentLevel > logLevel) return;

        var entity = new LogEntity();

        try
        {
            entity.Level = (Acl.Log.LogLevel)logLevel;
            entity.LoggerName = _innerLogger.Name;
            entity.Exception = exception;
            entity.Content = formatter(state, exception);
            //TODO:IP 
            _innerLogger.Log(entity);
        }
        finally
        {
        }
    }

    class NullDisposable : IDisposable
    {
        public static readonly IDisposable Instance = new NullDisposable();

        NullDisposable()
        {

        }

        public void Dispose()
        {
        }
    }
}

class AclLoggerFactory : ILoggerFactory
{
    public static readonly ILoggerFactory Instance = new AclLoggerFactory();
    public void AddProvider(ILoggerProvider provider)
    {
    }

    public ILogger CreateLogger(String categoryName) => AclLogProvider.Instance.CreateLogger(categoryName);

    public void Dispose()
    {
    }
}
